#include "file_tool.h"
#include <sys/types.h>
#include <sys/stat.h>

int backup_file(const char *src, const char *bak)
{
    if (!src || !bak)
        return -1;

    // 源文件不存在则无需备份
    int src_fd = open(src, O_RDONLY);
    if (src_fd == -1)
    {
        if (errno == ENOENT)
            return 0; // 源文件不存在，备份成功（视为空备份）
        perror("backup_file: open src failed");
        return -1;
    }
    close(src_fd);

    // 备份文件：使用rename原子操作
    if (rename(src, bak) == -1)
    {
        perror("backup_file: rename failed");
        return -1;
    }
    return 0;
}

// 恢复备份文件（返回0成功，-1失败）
int restore_backup(const char *bak, const char *src)
{
    if (!bak || !src)
        return -1;

    // 备份文件不存在则无法恢复
    int bak_fd = open(bak, O_RDONLY);
    if (bak_fd == -1)
    {
        if (errno == ENOENT)
            return 0; // 备份文件不存在，无需恢复
        perror("restore_backup: open bak failed");
        return -1;
    }
    close(bak_fd);

    // 恢复：覆盖原文件
    if (rename(bak, src) == -1)
    {
        perror("restore_backup: rename failed");
        return -1;
    }
    return 0;
}

// 删除备份文件（返回0成功，-1失败）
int delete_backup(const char *bak)
{
    if (!bak)
        return -1;
    if (unlink(bak) == -1 && errno != ENOENT)
    { // 忽略文件不存在的错误
        perror("delete_backup: unlink failed");
        return -1;
    }
    return 0;
}

off_t get_file_size(const char *filename)
{
    struct stat st;
    if (stat(filename, &st) == -1)
    {
        return 0;
    }
    return st.st_size;
}

int clear_file(const char *filename)
{
    // unlink(filename); // 删除文件
    if (!filename)
    {
        fprintf(stderr, "clear_file: filename is NULL\n");
        return -1;
    }
    int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644);
    if (fd == -1)
    {
        perror("aof_clear: open failed");
        return -1;
    }
    // 无需写入内容，O_TRUNC 已将文件长度截断为0
    close(fd);
    return 0;
}

// 生成不存在的文件
int createFileIfNotExist(const char* filename) {
    // 检查文件是否存在（F_OK 表示检查“存在性”）
    if (access(filename, F_OK) == 0) {
        printf("文件 %s 已存在，直接返回\n", filename);
        return 0;
    }

    // 文件不存在，尝试创建
    FILE* fp = fopen(filename, "w");  // "w" 模式会创建新文件（若不存在）
    if (fp == NULL) {
        printf("创建文件 %s 失败\n", filename);
        return -1;
    }

    fclose(fp);  // 关闭文件，确保资源回收
    printf("文件 %s 创建成功\n", filename);
    return 0;
}

// 设置阻塞
int set_socket_blocking(int sock_fd)
{
    // 1. 获取当前 socket 的状态标志
    int flags = fcntl(sock_fd, F_GETFL, 0);
    if (flags == -1)
    {
        perror("fcntl F_GETFL failed");
        return -1;
    }

    // 2. 清除 O_NONBLOCK 标志（阻塞模式 = 非阻塞标志位为 0）
    flags &= ~O_NONBLOCK; // 关键：通过按位取反清除非阻塞标志

    // 3. 应用新的标志位
    if (fcntl(sock_fd, F_SETFL, flags) == -1)
    {
        perror("fcntl F_SETFL failed");
        return -1;
    }
    return 0;
}

int set_socket_noblock(int sock_fd)
{
    // 关键：设置sock_fd为非阻塞模式
    int flags = fcntl(sock_fd, F_GETFL, 0);
    if (flags == -1)
    {
        perror("fcntl F_GETFL failed");
        return -1;
    }

    if (fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK) == -1)
    {
        perror("slave: set sock_fd nonblock failed");
        close(sock_fd);
        return -1;
    }
    return 0;
}

int is_non_blocking(int fd)
{
    // 获取文件描述符的当前状态标志
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags == -1)
    {
        return -1; // fcntl 失败（如 fd 无效），errno 已由 fcntl 设置
    }
    // 检查 O_NONBLOCK 标志是否存在
    return (flags & O_NONBLOCK) ? 1 : 0;
}

int is_blocking(int fd)
{
    int non_block = is_non_blocking(fd);
    if (non_block == -1)
    {
        return -1; // 传递错误（errno 已由 is_non_blocking 保留）
    }
    // 阻塞模式 = 非非阻塞模式
    return non_block ? 0 : 1;
}